/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */
package fr.generali.accueilclient.client.assembler.input;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.om.IClientParticulier;
import fr.generali.accueilclient.client.om.IClientProfessionnel;
import fr.generali.accueilclient.client.om.IIndicateursDemat;
import fr.generali.accueilclient.client.om.IPersonnePhysique;
import fr.generali.accueilclient.client.om.NaturePersonne;
import fr.generali.accueilclient.utils.constantes.CodeCiviliteSexeEnum;
import fr.generali.accueilclient.utils.constantes.CodeEtatPersonneEnum;
import fr.generali.accueilclient.utils.constantes.CodePopulationEnum;
import fr.generali.accueilclient.utils.constantes.NaturePersonneEnum;
import fr.generali.accueilclient.utils.constantes.StatutClientEnum;
import fr.generali.refservcommuns.clients.prima.DatedMonetaryQuantityRangeValue;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoBlocNote;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoCategorieSocioProfessionnelle;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoDetailActiviteProfessionnelle;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoDetailNaissance;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.detailspersonnes.DtoDetailSituationFamiliale;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.gestionrelationsaffaire.DtoRelationClient;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoIndicateurDematerialisation;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonnePhysique;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoSecteurActivite;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoVisibilite;

/**
 * @author selrhazala
 */
@Component("personnePhysiqueToDtoPersonnePhysiqueConverter")
public class PersonnePhysiqueToDtoPersonnePhysiqueConverter implements
                Converter<IPersonnePhysique, DtoPersonnePhysique> {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(PersonnePhysiqueToDtoPersonnePhysiqueConverter.class);

    /**
     * {@inheritDoc}
     */
    public DtoPersonnePhysique convert(IPersonnePhysique personnePhysique) {
        // init date du jour
        XMLGregorianCalendar dateDuJour = null;
        try {
            GregorianCalendar gCalendar1 = new GregorianCalendar();
            gCalendar1.setTime(new Date());
            dateDuJour = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar1);
        } catch (DatatypeConfigurationException e) {
            LOGGER.debug("erreur datatype configuration");
        }

        return buildPersonnePhysique(personnePhysique, dateDuJour);
    }

    /**
     * @param personnePhysique la personne physique
     * @param dateDuJour la date du jour
     * @return DtoPersonnePhysique
     */
    public DtoPersonnePhysique buildPersonnePhysique(IPersonnePhysique personnePhysique, XMLGregorianCalendar dateDuJour) {

        DtoPersonnePhysique dtoPersonnePhysique = new DtoPersonnePhysique();

        // Critères de personne physique en commun pour les personnes physiques
        dtoPersonnePhysique.setNaturePersonne(NaturePersonneEnum.NATURE_PHYSIQUE.getCode());
        dtoPersonnePhysique.setCivilite(personnePhysique.getCivilite());
        dtoPersonnePhysique.setNom(personnePhysique.getNom());
        dtoPersonnePhysique.setNomJeuneFille(personnePhysique.getNomJeuneFille());
        dtoPersonnePhysique.setPrenom(personnePhysique.getPrenom());
        dtoPersonnePhysique.setNationalite(personnePhysique.getNationalite());
        dtoPersonnePhysique.setTitre(personnePhysique.getTitre());
        dtoPersonnePhysique.setVip(personnePhysique.isClientVIP());
        dtoPersonnePhysique.setIndicateurCollaborateur(personnePhysique.isCollaborateurGenerali());
        dtoPersonnePhysique.setDenominationFUE(personnePhysique.getIdClientFue());
        dtoPersonnePhysique.setDateCreation(dateDuJour);
        dtoPersonnePhysique.setDateDebutClient(dateDuJour);
        dtoPersonnePhysique.setRaisonConnaissanceTiers(personnePhysique.getOrigineClient());
        dtoPersonnePhysique.setCodeTypeAffiliation(personnePhysique.getRegimeObligatoire());
        dtoPersonnePhysique.setEtat(CodeEtatPersonneEnum.CODE_ETAT_0.getCode());

        if (StringUtils.isNotEmpty(personnePhysique.getCivilite())) {
            // le sexe est déduit de la civilité
            if (CodeCiviliteSexeEnum.CODE_CIVILITE_01.getCode().equals(personnePhysique.getCivilite())) {
                dtoPersonnePhysique.setSexe(CodeCiviliteSexeEnum.CODE_SEXE_02.getCode());
            } else {
                dtoPersonnePhysique.setSexe(CodeCiviliteSexeEnum.CODE_SEXE_01.getCode());
            }
        } else {
            dtoPersonnePhysique.setSexe(personnePhysique.getSexe());
        }

        if (personnePhysique.getDateDeces() == null || StringUtils.isEmpty(personnePhysique.getDateDeces().toString())) {
            dtoPersonnePhysique.setVivante(true);
        } else {
            dtoPersonnePhysique.setVivante(false);
        }

        DtoRelationClient dtoRelationClient = new DtoRelationClient();
        dtoRelationClient.setTitreCourrier(personnePhysique.getTitreCourrier());
        dtoPersonnePhysique.setRelationClient(dtoRelationClient);

        DtoVisibilite dtoVisibilite = new DtoVisibilite();
        dtoVisibilite.setIdentifiantIntermediaire(personnePhysique.getCodeIntermediaire());
        dtoVisibilite.setIdentifiantClientAgent(personnePhysique.getNumeroClientAgent());
        dtoVisibilite.setIdentifiantPointVente(personnePhysique.getPointDeVente());
        dtoVisibilite.setIdentifiantChargeClientele(personnePhysique.getChargeClientele());
        dtoVisibilite.setCodePopulation(CodePopulationEnum.POPULATION_ACC.getCode());
        dtoPersonnePhysique.setVisibilite(dtoVisibilite);

        if (personnePhysique.getDateNaissance() != null) {
            try {
                GregorianCalendar gCalendar2 = new GregorianCalendar();
                gCalendar2.setTime(personnePhysique.getDateNaissance());
                XMLGregorianCalendar xmlCalendar2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar2);
                dtoPersonnePhysique.setDateNaissance(xmlCalendar2);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        if (personnePhysique.getDateDeces() != null) {
            try {
                GregorianCalendar gCalendarDeces = new GregorianCalendar();
                gCalendarDeces.setTime(personnePhysique.getDateDeces());
                XMLGregorianCalendar xmlCalendarDeces =
                                DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendarDeces);
                dtoPersonnePhysique.setDateDeces(xmlCalendarDeces);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        DtoDetailNaissance dtoDetailNaissance = new DtoDetailNaissance();
        dtoDetailNaissance.setCodePostalNaissance(personnePhysique.getCpNaissance());
        dtoDetailNaissance.setLieuNaissance(personnePhysique.getLieuNaissance());
        dtoDetailNaissance.setPaysDeNaissance(personnePhysique.getPaysNaissance());
        dtoPersonnePhysique.setDetailNaissance(dtoDetailNaissance);

        DtoDetailSituationFamiliale dtoDetailSituationFamiliale = new DtoDetailSituationFamiliale();
        dtoDetailSituationFamiliale.setEtatUnion(personnePhysique.getSituationFamiliale());
        dtoDetailSituationFamiliale.setStatutMatrimonial(personnePhysique.getRegimeMatrimonial());
        if (StringUtils.isNotEmpty(personnePhysique.getNbEnfants())) {
            dtoDetailSituationFamiliale.setNombreEnfants(BigInteger.valueOf(Long.parseLong(personnePhysique
                            .getNbEnfants())));
        }
        dtoPersonnePhysique.setDetailSituationFamiliale(dtoDetailSituationFamiliale);

        DtoCategorieSocioProfessionnelle dtoCategorieSocioProfessionnelle = new DtoCategorieSocioProfessionnelle();

        // on prend le niveau le plus précis renseigné
        if (StringUtils.isNotEmpty(personnePhysique.getStatutProfessionnel4())) {
            dtoCategorieSocioProfessionnelle.setCodePCS(personnePhysique.getStatutProfessionnel1() + ";"
                            + personnePhysique.getStatutProfessionnel2() + ";"
                            + personnePhysique.getStatutProfessionnel3() + ";"
                            + personnePhysique.getStatutProfessionnel4());
        } else {
            if (StringUtils.isNotEmpty(personnePhysique.getStatutProfessionnel3())) {
                dtoCategorieSocioProfessionnelle.setCodePCS(personnePhysique.getStatutProfessionnel1() + ";"
                                + personnePhysique.getStatutProfessionnel2() + ";"
                                + personnePhysique.getStatutProfessionnel3() + ";");
            } else {
                if (StringUtils.isNotEmpty(personnePhysique.getStatutProfessionnel2())) {
                    dtoCategorieSocioProfessionnelle.setCodePCS(personnePhysique.getStatutProfessionnel1() + ";"
                                    + personnePhysique.getStatutProfessionnel2() + ";;");
                } else {
                    if (StringUtils.isNotEmpty(personnePhysique.getStatutProfessionnel1())) {
                        dtoCategorieSocioProfessionnelle.setCodePCS(personnePhysique.getStatutProfessionnel1() + ";;;");
                    }
                }
            }
        }

        dtoPersonnePhysique.setCategorieSocioProfessionnelle(dtoCategorieSocioProfessionnelle);

        DtoSecteurActivite dtoSecteurActivite = new DtoSecteurActivite();
        dtoSecteurActivite.setCode(personnePhysique.getSecteurActivite());
        dtoPersonnePhysique.setSecteurActivite(dtoSecteurActivite);

        List<DtoDetailActiviteProfessionnelle> listDap = new ArrayList<DtoDetailActiviteProfessionnelle>();
        DtoDetailActiviteProfessionnelle dtoDetailActivitePro = new DtoDetailActiviteProfessionnelle();

        DatedMonetaryQuantityRangeValue dmqrvRevenuBorne = new DatedMonetaryQuantityRangeValue();
        if (StringUtils.isNotEmpty(personnePhysique.getRevenuAnnuel())) {
            dmqrvRevenuBorne.setValue(BigDecimal.valueOf(Long.parseLong(personnePhysique.getRevenuAnnuel())));
            dmqrvRevenuBorne.setCodeIndicateurSaisie(personnePhysique.getRevenuAnnuel());
        }
        dtoDetailActivitePro.setRevenuBorne(dmqrvRevenuBorne);

        DtoBlocNote dtoBlocNote = new DtoBlocNote();
        dtoBlocNote.setPrecisionProfession(personnePhysique.getPrecisionProfession());
        dtoDetailActivitePro.setBlocNote(dtoBlocNote);

        if (StringUtils.isNotEmpty(personnePhysique.getAnneeRevenu())) {
            try {
                GregorianCalendar gPeriodeFiscale = new GregorianCalendar();
                gPeriodeFiscale.set(Integer.parseInt(personnePhysique.getAnneeRevenu()), 1, 1);
                XMLGregorianCalendar periodeFiscale =
                                DatatypeFactory.newInstance().newXMLGregorianCalendar(gPeriodeFiscale);
                dtoDetailActivitePro.setPeriodeFiscale(periodeFiscale);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        listDap.add(dtoDetailActivitePro);
        dtoPersonnePhysique.getDetailActiviteProfessionnelle().addAll(listDap);

        if (personnePhysique.getFinActivite() != null) {
            try {
                GregorianCalendar gCalendar3 = new GregorianCalendar();
                gCalendar3.setTime(personnePhysique.getFinActivite());
                XMLGregorianCalendar xmlCalendar3 = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar3);
                dtoPersonnePhysique.setDateRetraite(xmlCalendar3);
            } catch (DatatypeConfigurationException e) {
                LOGGER.debug("erreur datatype configuration");
            }
        }

        if (NaturePersonne.PROFESSIONNEL.equals(personnePhysique.getNaturePersonne())) {
            IClientProfessionnel clientProfessionnel = IClientProfessionnel.class.cast(personnePhysique);
            dtoPersonnePhysique = buildProfessionnelPP(dtoPersonnePhysique, clientProfessionnel);
        } else if (NaturePersonne.PARTICULIER.equals(personnePhysique.getNaturePersonne())) {
            IClientParticulier clientParticulier = IClientParticulier.class.cast(personnePhysique);
            dtoPersonnePhysique = buildParticulier(dtoPersonnePhysique, clientParticulier);
        }

        if (personnePhysique.getIndicateursDemat() != null) {

            Converter<IIndicateursDemat, List<DtoIndicateurDematerialisation>> converterIndDemat =
                            new IndicateursDemat2DtoIndicateurDematConverter();

            List<DtoIndicateurDematerialisation> listeDtoIndDemat =
                            converterIndDemat.convert(personnePhysique.getIndicateursDemat());

            if (CollectionUtils.isNotEmpty(listeDtoIndDemat)) {
                dtoPersonnePhysique.getInformationDematerialisation().addAll(listeDtoIndDemat);
            }
        }

        return dtoPersonnePhysique;
    }

    /**
     * @param dtoPersonnePhysique la personne physique
     * @param clientParticulier le particulier
     * @return DtoPersonneMorale
     */
    public DtoPersonnePhysique buildParticulier(DtoPersonnePhysique dtoPersonnePhysique,
                    IClientParticulier clientParticulier) {
        // Critères concernant uniquement le particulier

        return dtoPersonnePhysique;
    }

    /**
     * @param dtoPersonnePhysique la personne physique
     * @param clientProfessionnel le professionnel
     * @return DtoPersonneMorale
     */
    public DtoPersonnePhysique buildProfessionnelPP(DtoPersonnePhysique dtoPersonnePhysique,
                    IClientProfessionnel clientProfessionnel) {
        // Critères concernant uniquement le professionnel - Partie PP
        dtoPersonnePhysique.setNaturePersonne(NaturePersonneEnum.NATURE_PHYSIQUE.getCode());
        dtoPersonnePhysique.setStatutClient(StatutClientEnum.CODE_STATUT_CLIENT_PP.getCode());

        return dtoPersonnePhysique;
    }

}
